package cn.lcc.ymcc.service.impl;

import cn.lcc.ymcc.fegin.IUaaFeignClient;
import cn.lcc.ymcc.domain.Login;
import cn.lcc.ymcc.domain.User;
import cn.lcc.ymcc.domain.UserAccount;
import cn.lcc.ymcc.domain.UserBaseInfo;
import cn.lcc.ymcc.dto.RegParamDto;
import cn.lcc.ymcc.mapper.UserAccountMapper;
import cn.lcc.ymcc.mapper.UserBaseInfoMapper;
import cn.lcc.ymcc.mapper.UserMapper;
import cn.lcc.ymcc.result.JSONResult;
import cn.lcc.ymcc.service.IUserService;
import cn.lcc.ymcc.util.AssertUtil;
import cn.lcc.ymcc.util.BitStatesUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author lcc
 * @since 2022-12-05
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private IUaaFeignClient uaaFeignClient;

    @Autowired
    private UserAccountMapper userAccountMapper;
    @Autowired
    private UserBaseInfoMapper userBaseInfoMapper;

    @Override
    public User queryByPhone(String phone) {
        Wrapper<User> wrapper=new EntityWrapper<>();
        //使用调用方法的形式，生成sql
        wrapper.eq("phone",phone); // where phone=#{phone}
        return selectOne(wrapper);
    }



    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void register(RegParamDto regParamDto) {
        //1.对数据进行校验【校验图形验证码和手机验证码是否正确】
        checkVerifyCode(regParamDto);

        //2.保存t_login里面的数据 为了得到注解id
        Long loginId = saveLogin(regParamDto);
        //3.保存t_user---为了得到主键id
        User user = saveUser(regParamDto, loginId);
        //4.保存t_user_account
        saveUserAccount(user);
        //5.保存t_user_base_info
        saveUserInfo(user,regParamDto.getRegChannel());
    }
    private Long saveLogin(RegParamDto regParamDto){
        Login login = new Login();
        login.setUsername(regParamDto.getMobile());
        login.setPassword(regParamDto.getPassword());
        login.setType(Login.LOG_WEB);
        //发起远程调用
        JSONResult jsonResult = uaaFeignClient.saveLogin(login);
        Long aLong = Long.valueOf(jsonResult.getData().toString());
        AssertUtil.isNotEquals(aLong,-1L,"异常");
        return aLong;
    }

    private void saveUserInfo(User user, Integer regChannel) {
        UserBaseInfo info = new UserBaseInfo();
        info.setId(user.getId());
        info.setCreateTime(System.currentTimeMillis());
        info.setGrowScore(0);
        info.setRegChannel(regChannel);
        info.setLevel(0);
        userBaseInfoMapper.insert(info);

    }

    private void saveUserAccount(User user) {
        UserAccount userAccount = new UserAccount();
        userAccount.setId(user.getId());
        userAccount.setCreateTime(System.currentTimeMillis());
        userAccount.setFrozenAmount(new BigDecimal("0"));
        userAccount.setUsableAmount(new BigDecimal("0"));
        userAccountMapper.insert(userAccount);
    }

    private User saveUser(RegParamDto regParamDto, Long loginId) {
        User u = new User();
        u.setCreateTime(System.currentTimeMillis());
        u.setLoginId(loginId);
        u.setPhone(regParamDto.getMobile());
        u.setNickName(regParamDto.getMobile());
        u.setSecLevel(0);
        //设置用户的状态
        /*
            账户安全认证：
                1.手机号认证
                2.邮箱认证
                3.密保问题
                4.实名制认证
                以上的认证 可能会出现任意的组合

                方案1：
                    最简单的方案 ，设计4个字段，没做就是0  做了就是1



         */
        long state = BitStatesUtils.addState(BitStatesUtils.OP_REGISTED, BitStatesUtils.OP_ACTIVED);
        state = BitStatesUtils.addState(state,BitStatesUtils.OP_AUTHED_PHONE);
        //以后有什么新的认证，使用原有的状态+新的状态
        u.setBitState(state);
        insert(u);
        return u;
    }


    private void checkVerifyCode(RegParamDto regParamDto){
        //1.验证码图形验证码  TODO
        //2.验证手机验证码
        String codeInRedis = redisTemplate.opsForValue().get("register:" + regParamDto.getMobile()).toString();
        AssertUtil.isNotNull(codeInRedis,"手机验证码无效，请重新发送");
        //3.取出验证码进行比较
        String code = codeInRedis.split(":")[0];
        AssertUtil.isEqualsTrim(regParamDto.getSmsCode(),code,"验证码错误");

    }
}
